import { Component, ElementRef, ViewChild } from '@angular/core';
import { SignalService } from '../video.service';

@Component({
  selector: 'app-video',
  templateUrl: './video.component.html',
  standalone: false,
  styleUrl: './video.component.css',
})
export class VideoComponent {
  @ViewChild('localVideo') localVideo!: ElementRef<HTMLVideoElement>;
  @ViewChild('remoteVideo') remoteVideo!: ElementRef<HTMLVideoElement>;

  roomName = '';
  callStarted = false;
  joined = false;
  errorMsg = '';
  isSwapped = true;

  private pc!: RTCPeerConnection;
  private localStream!: MediaStream;

  constructor(private signaling: SignalService) {}

  ngOnInit() {
    this.signaling.onMessage(async (msg) => {
      if (msg.type === 'joined') {
        this.joined = true;
        this.errorMsg = '';
        console.log(`Joined room: ${msg.room}`);
      } else if (msg.type === 'error') {
        this.errorMsg = msg.message;
      }

      if (!this.pc) return;

      if (msg.type === 'offer') {
        await this.pc.setRemoteDescription(new RTCSessionDescription(msg.offer));
        const answer = await this.pc.createAnswer();
        await this.pc.setLocalDescription(answer);
        this.signaling.send({ type: 'answer', answer });
        this.callStarted = true;
      } else if (msg.type === 'answer') {
        await this.pc.setRemoteDescription(new RTCSessionDescription(msg.answer));
      } else if (msg.type === 'candidate') {
        await this.pc.addIceCandidate(new RTCIceCandidate(msg.candidate));
      } else if (msg.type === 'hangup') {
        this.cleanupVideos();
      }
    });
  }

  joinRoom() {
    if (!this.roomName) {
      this.errorMsg = '房间号不能为空';
      return;
    }
    this.signaling.connect(); // 初始化 WebSocket 连接
    this.signaling.send({ type: 'join', room: this.roomName });
  }

  async startCall() {
    this.pc = new RTCPeerConnection();
    this.localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    this.localVideo.nativeElement.srcObject = this.localStream;
    this.localStream.getTracks().forEach(track => this.pc.addTrack(track, this.localStream));

    this.pc.ontrack = (event) => {
      this.remoteVideo.nativeElement.srcObject = event.streams[0];
    };

    this.pc.onicecandidate = (event) => {
      if (event.candidate) {
        this.signaling.send({ type: 'candidate', candidate: event.candidate });
      }
    };

    const offer = await this.pc.createOffer();
    await this.pc.setLocalDescription(offer);
    this.signaling.send({ type: 'offer', offer });

    this.callStarted = true;
  }

  hangUp() {
    if (this.pc) {
      this.pc.close();
      this.pc = undefined!;
    }
    this.cleanupVideos();
    this.signaling.send({ type: 'hangup' });
  }

  private cleanupVideos() {
    this.callStarted = false;
    if (this.localStream) {
      this.localStream.getTracks().forEach(track => track.stop());
      this.localStream = undefined!;
    }
    this.localVideo.nativeElement.srcObject = null;
    this.remoteVideo.nativeElement.srcObject = null;
  }

  leaveRoom() {
    if (this.pc) {
      this.pc.close();
      this.pc = undefined!;
    }
    this.cleanupVideos();
    this.signaling.send({ type: 'hangup' });

    this.signaling.send({ type: 'leave', room: this.roomName });
    this.signaling.leaveRoom();
    this.roomName = '';
    this.joined = false;
  }

  swapVideo() {
    this.isSwapped = !this.isSwapped;
  }
}
